from common.db import models
from decimal import Decimal
from django.contrib.postgres.fields import JSONField
from tuntun.settings import GETUI
import time
from hashlib import sha256
import requests


# Create your models here.


class SystemSetting(models.Model):
    """
    系统设置（全局设置）
    """

    init_data = [
        {"postage": Decimal("12.00")}
    ]

    postage = models.DecimalField("邮寄费", max_digits=10, decimal_places=2, default=Decimal('0.01'))
    procedure = models.DecimalField("手续费", max_digits=10, decimal_places=2, default=Decimal('0.01'))

    getui_authtoken = models.CharField("个推AuthToken", blank=True, null=True)
    getui_authtoken_expire_at = models.BigIntegerField("个推AuthToken失效时间(秒)", default=0)

    aliyun_oss_sts_access_key_id = models.CharField("OSS-STS-AKID", blank=True, null=True)
    aliyun_oss_sts_access_key_secret = models.CharField('OSS-STS-AKS', blank=True, null=True)
    aliyun_oss_sts_security_token = models.CharField('OSS-STS-token', blank=True, null=True)
    aliyun_oss_sts_expire_at = models.BigIntegerField(default=0)

    app_service_protocol = models.TextField(verbose_name='App服务协议', blank=True, null=True)
    tun_level_intro = models.TextField(verbose_name='囤级说明', blank=True, null=True)

    kefu_phone = models.CharField(verbose_name='客服电话', blank=True, null=True)
    jubao_phone = models.CharField(verbose_name='举报电话', blank=True, null=True)

    @classmethod
    def get_procedure(cls):
        obj = cls.objects.first()
        return obj.procedure

    @classmethod
    def get_postage(cls, src_code, dest_code, weight_kg_amount):
        from sdks.express.sf_express import calc_price
        return calc_price(src_code, dest_code, weight_kg_amount)

    def refresh_getui_authtoken(self):
        app_id = GETUI['AppID']
        app_key = GETUI['AppKey']
        master_secret = GETUI['MasterSecret']
        url = 'https://restapi.getui.com/v1/%s/auth_sign' % app_id
        print(url)
        method = 'POST'
        timestamp = int(time.time()) * 1000
        raw_str = app_key + str(timestamp) + master_secret
        hashobj = sha256()
        hashobj.update(raw_str.encode())
        sign = hashobj.hexdigest()
        data = {'sign': sign, 'timestamp': timestamp, "appkey": app_key}
        r = requests.request(method=method, url=url, json=data)
        print(r.text)
        if r.status_code == 200:
            resp = r.json()
            if 'result' in resp and resp['result'] == 'ok':
                self.getui_authtoken = resp['auth_token']
                self.getui_authtoken_expire_at = int(int(resp['expire_time']) / 1000)
                self.save()
            else:
                print(resp)
        else:
            print(r.text)

    def get_getui_authtoken(self):
        if self.getui_authtoken_expire_at > int(time.time()):
            return self.getui_authtoken
        else:
            self.refresh_getui_authtoken()
            return self.getui_authtoken

    @classmethod
    def get_repo_cost_preferential_amount(cls, user, repo_cost):
        """
        获取优惠仓储费价格-忽略model里的repo_cost_preferential
        :param user: 用户
        :param repo_cost: 仓储费
        :return:
        """
        level_right = user.get_user_level_right()
        if level_right:
            return round(Decimal(level_right.repo_preferential_percent) * Decimal(repo_cost), 2)
        else:
            return Decimal('0.00')

    @classmethod
    def get_procedure_preferential_amount(cls, user, order_amount):
        """
        获取优惠手续费
        :param user: 用户
        :param amount: 金额
        :param order_amount: 订单金额
        :return:
        """
        procedure_amount = cls.get_procedure()*order_amount

        level_right = user.get_user_level_right()
        if level_right:
            procedure_preferential_amount = round(procedure_amount*level_right.procedure_preferential_percent, 2)
        else:
            procedure_preferential_amount = Decimal('0.00')

        procedure_real_pay_amount = procedure_amount - procedure_preferential_amount
        return {
            "procedure_amount": procedure_amount,
            "procedure_preferential_amount": procedure_preferential_amount,
            "procedure_real_pay_amount": procedure_real_pay_amount
        }

    @classmethod
    def get_postage_preferential(cls, user, postage):
        from apps.user.models import UserTunLevelRightTimes
        import time
        now_timestamp = time.time()
        level_right = user.get_user_level_right()
        postage_preferential = Decimal('0.00')
        use_take_out_free_postage_right_id = None
        if level_right:
            if level_right.take_out_free_postage_times_1y < 0:
                postage_preferential = Decimal(postage)
            else:
                right_time = UserTunLevelRightTimes.objects.filter(user=user, right=UserTunLevelRightTimes.Right.TAKE_OUT_FREE_POSTAGE.name, used=False, expire_at__gt=now_timestamp).first()
                if right_time:
                    postage_preferential = Decimal(postage)
                    use_take_out_free_postage_right_id = right_time.id
                else:
                    postage_preferential = Decimal('0.00')
        else:
            postage_preferential = Decimal('0.00')
        return postage_preferential, use_take_out_free_postage_right_id

    @classmethod
    def get_aliyun_oss_sts_token(cls):
        import time
        from sdks.aliyunoss import fetch_sts_token
        from tuntun.settings import ALIYUN_OSS
        obj = cls.objects.first()
        if obj.aliyun_oss_sts_expire_at - time.time() < 30:
            token = fetch_sts_token(ALIYUN_OSS['AccessKeyId'], ALIYUN_OSS['AccessKeySecret'],
                                    ALIYUN_OSS['WriterRolArn'])
            obj.aliyun_oss_sts_access_key_id = token.access_key_id
            obj.aliyun_oss_sts_access_key_secret = token.access_key_secret
            obj.aliyun_oss_sts_security_token = token.security_token
            obj.aliyun_oss_sts_expire_at = token.expiration
            obj.save()
        return {
            "access_key_id": obj.aliyun_oss_sts_access_key_id,
            "access_key_secret": obj.aliyun_oss_sts_access_key_secret,
            "security_token": obj.aliyun_oss_sts_security_token,
            "expiration": obj.aliyun_oss_sts_expire_at,
        }

    @classmethod
    def get_app_service_protocol(cls):
        obj = cls.objects.first()
        return obj.app_service_protocol if obj.app_service_protocol else ''


class SystemLog(models.Model):
    class Level(models.Choices):
        INFO = 'INFO'
        DEBUG = 'DEBUG'
        WARN = 'WARN'
        ERROR = 'ERROR'

    level = models.CharField(verbose_name='Level', choices=Level.get_choices(), default=Level.INFO.name)
    text_log = models.TextField(verbose_name='TextLog', blank=True, null=True)
    json_log = JSONField(verbose_name='JsonLog', default=[])

    @classmethod
    def info(cls, text_log, json_log=[]):
        return cls.objects.create(level=cls.Level.INFO.name, text_log=text_log, json_log=json_log)

    @classmethod
    def debug(cls, text_log, json_log=[]):
        return cls.objects.create(level=cls.Level.DEBUG.name, text_log=text_log, json_log=json_log)

    @classmethod
    def warn(cls, text_log, json_log=[]):
        return cls.objects.create(level=cls.Level.WARN.name, text_log=text_log, json_log=json_log)

    @classmethod
    def error(cls, text_log, json_log=[]):
        return cls.objects.create(level=cls.Level.ERROR.name, text_log=text_log, json_log=json_log)
